

#include "MathEditPoint.h"
#include <iostream>
#include "Node.h"

MathEditPoint::MathEditPoint(QWidget * parent)
: QLineEdit(parent) {
    connect(this, SIGNAL(textChanged(QString)),
            this, SLOT(upDateSize()));
    // TODO we can change upDateSize(QString) to upDateSize()

    // set up a validator
    QRegExp rx("([a-zA-Z]+[a-zA-Z_0-9]*)|"
            "((0x)?[0-9]+\\.?[0-9]*)|((0x)?[0-9]*\\.?[0-9]+)");
    QValidator *validator = new QRegExpValidator(rx, this);
    setValidator(validator);

    // clear out its content flags
    isNum = false;
    isId = false;

    // set background color & border style
    setStyleSheet("background: pink; border: 0px");

    // resize the input field
    adjustSize();
}

void MathEditPoint::keyPressEvent(QKeyEvent *event) {
    // see if line edit will use left or right arrow key
    int oldCursorPostion =  cursorPosition();
    // see if line edit will apply delete or backspace key
    int oldTextSize = text().size();
    // do the default things
    QLineEdit::keyPressEvent(event);
    // see if cursor moved
    bool cursorNotMoved = ( oldCursorPostion == cursorPosition() );
    // see if line edit did apply delete or backspace key
    bool textNotChanged = ( oldTextSize == text().size() );
    // ignore to send up to parent if ...
    if  (event->text().contains(QRegExp("[+\\-/^*()=,%]"))
            or (event->key() == Qt::Key_Backspace and textNotChanged)
            or (event->key() == Qt::Key_Delete and textNotChanged)
            or (event->key() == Qt::Key_Right and cursorNotMoved)
            or (event->key() == Qt::Key_Left and cursorNotMoved)
            or event->key() == Qt::Key_Enter // key on numberpad
            or event->key() == Qt::Key_Return ) { // key on letter pad
        event->ignore();
    } else {
        event->accept();
    }
}

QSize MathEditPoint::sizeHint() const {
    QSize bsize = QLineEdit::sizeHint();
    QFontMetrics fm(font());

    // find what QLineEdit::sizeHint() added to base size for frame
    // by see how much it added to its base calculation.
    int width = bsize.width() - fm.width(QLatin1Char('x')) * 17;
    // add to that the width needed by the content
    width += fm.width(text());

    bsize.setWidth(width);

    return bsize;
}

void MathEditPoint::focusOutEvent(QFocusEvent * event) {
    // base the notice of focuesOut up the tree.
    // when it gets to the top node it will check to see if it 
    // is an empty tree and remove its self if so
    QLineEdit::focusOutEvent(event);
    // cast the parent to a Node class
    Node *nodeParent = qobject_cast<Node *>(parent());
    if (nodeParent) {
        nodeParent->focusOut();
    }
}

void MathEditPoint::focusInEvent(QFocusEvent * event) {
    QLineEdit::focusInEvent(event);
    setCursorPosition(0);
}

void MathEditPoint::upDateSize() {
    adjustSize();
    updateGeometry();
    Node *nodeParent = qobject_cast<Node *>(parent());
    if (nodeParent) {
        nodeParent->upDateSize();
    } else {
        Q_ASSERT_X(0, "MathEditPoint::keyPressEvent", "Parent was not a Node class.");
    }

    // clear out its content flags
    isNum = false;
    isId = false;

    // regex patterns to identify what is in QLineEdit
    QRegExp id("([a-zA-Z]+[a-zA-Z_0-9]*)");
    QRegExp num("((0x)?[0-9]+\\.?[0-9]*)|((0x)?[0-9]*\\.?[0-9]+)");

    // Set background color based on what is in QLineEdit
    if (id.exactMatch(text())) {
        setStyleSheet("background: lightBlue; border: 0px");
        isId = true;
        // TODO add more formating if it is a recognized id
    } else if (num.exactMatch(text())) {
        setStyleSheet("background: LightGreen; border: 0px");
        isNum = true;
    } else {
        setStyleSheet("background: pink; border: 0px");
    }

}